package com.erp.app.report.genericInquiry;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionServlet;

import com.erp.app.common.ProjectConstants;
import com.erp.app.report.genericInquiry.inquiryJava.criteria.InquiryJavaSrchCriteria;
import com.erp.app.report.genericInquiry.inquiryJava.vo.InquiryJavaVo;
import com.erp.framework.model.delegate.SimplePageEditStyleDelegate;
import com.erp.framework.types.CustomBigInteger;
import com.erp.framework.util.logger.Logger;

public abstract class GenericFileGenerator {
	protected GenericInquirySearchForm form = null;
	protected Collection srcs = null;
	protected boolean isUseDynamicClass = false;
	
	public GenericFileGenerator(GenericInquirySearchForm form) {
		this.form = form;
	}
	
    public void generate(ActionMapping mapping, 
            HttpServletRequest request, 
            HttpServletResponse response, 
            ActionServlet servlet, 
            ActionErrors errors) throws Exception {
        
        OutputStream dest = null;
        ByteArrayOutputStream baos = null;
        
        try {
            preprocess(request, response, servlet, errors);
            baos = genContent(mapping, request, response, servlet, errors);            
            postprocess(baos, request, response, servlet, errors);
            dest = getOutputStream(request, response, servlet, errors);
            dump(dest, baos);

            baos = null;
        } catch (Exception e) {
            //response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
        	throw e;
        } finally {
        	form.setReportResultList(null);
            form = null;
            srcs = null;
        }
    }
    
    protected void postprocess(ByteArrayOutputStream baos,
            HttpServletRequest request, 
            HttpServletResponse response,
            ActionServlet servlet,
            ActionErrors errors) {
        response.setStatus(HttpServletResponse.SC_OK);
        response.setContentLength(baos.size());        
    }
    
    protected void dump(OutputStream dest, ByteArrayOutputStream baos) throws IOException {
        baos.writeTo(dest);
        dest.close();
    }
    
    protected OutputStream getOutputStream(
            HttpServletRequest request, 
            HttpServletResponse response,
            ActionServlet servlet,
            ActionErrors errors) throws IOException {
        return response.getOutputStream();
    }
    
    protected abstract void preprocess(
            HttpServletRequest request, 
            HttpServletResponse response,
            ActionServlet servlet,
            ActionErrors errors);
    
    protected abstract ByteArrayOutputStream genContent(
            ActionMapping mapping,
            HttpServletRequest request, 
            HttpServletResponse response,
            ActionServlet servlet,
            ActionErrors errors) throws Exception;

	public boolean isUseDynamicClass() {
		return isUseDynamicClass;
	}

	public void setUseDynamicClass(boolean isUseDynamicClass) {
		this.isUseDynamicClass = isUseDynamicClass;
	}
    
	protected void initReportClasses(String inquiryType, String javaType, ServletContext sc) {
    	srcs = (Collection) sc.getAttribute(ProjectConstants.PROJECT_PREFIX + "." + 
        		inquiryType + "." +
        		javaType);
        
        if (srcs == null) {
            InquiryJavaSrchCriteria inqJavaCri = new InquiryJavaSrchCriteria();

            inqJavaCri.setSrchInquiryTypeFr(inquiryType);
            inqJavaCri.setSrchInquiryTypeTo(inquiryType);
            inqJavaCri.setSrchJavaTypeFr(javaType);
            inqJavaCri.setSrchJavaTypeTo(javaType);

            InquiryJavaVo dummy = new InquiryJavaVo();
            SimplePageEditStyleDelegate dg = new SimplePageEditStyleDelegate();
            
            Collection c = null;
			
            try {
				//c = dg.findByCriteria(dummy, inqJavaCri, "TEMP USER CODE");
                c = dg.findByCriteria(dummy, inqJavaCri);
			} catch (Exception e) {
				Logger.logExceptions(e);
			} 
			
            srcs = c;
            
            if (srcs != null && srcs.size() == 0)
            	srcs = null;
            
            sc.setAttribute(ProjectConstants.PROJECT_PREFIX + "." + 
            		inquiryType + "." +
            		javaType, srcs);
        }
    }
    
    protected ByteArrayOutputStream createReportByteArray(
    		String javaType, 
    		boolean useShared, 
    		ActionMapping mapping, 
    		HttpServletRequest request, 
    		HttpServletResponse response, 
    		ActionServlet servlet, 
    		ActionErrors errors) throws Exception {
    	ServletContext sc = servlet.getServletContext();
    	String inquiryType = form.getInquiryType();
    	
    	if (isUseDynamicClass) {
	        if (useShared) {
	        	initReportClasses(ProjectConstants.GENERIC_REPORT_COMMON_CLASS, javaType, sc);
	        } else {
	        	initReportClasses(inquiryType, javaType, sc);
	        }
    	}

        if (srcs == null) {
        	if (useShared && isUseDynamicClass)
        		Logger.error("Unable to locate shared " + javaType + " class file in Generic Inquiry (" + inquiryType + ")");        	
        	
            return null;
        }
        
    	byte[][] javaSource = null;
        String[] className = null;
        CustomBigInteger[] isMainClass = null;
        javaSource = new byte[srcs.size()][];
        className = new String[srcs.size()];
        isMainClass = new CustomBigInteger[srcs.size()];        

        int pos = 0;
        for (Iterator it = srcs.iterator(); it.hasNext();) {
            InquiryJavaVo vo = (InquiryJavaVo)it.next();
            javaSource[pos] = vo.getJavaSource();
            className[pos] = vo.getClassName();
            isMainClass[pos] = vo.getIsMainClass();
            pos++;
        }

        ArrayList rslt = (ArrayList) form.getReportResultList();
        LoadReportClass lc = new LoadReportClass();
        
        return lc.load(mapping, (ActionForm)form,request,response, errors, servlet, rslt, className,javaSource, isMainClass);    	
    }    
}
